export class Program {
    constructor(gl, vertSrc, fragSrc) {
        this._gl = gl;
        this._firstUse = true;

        this.attributes = {};
        this.uniforms = {};

        this.program = gl.createProgram();

        this._vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.attachShader(this.program, this._vertShader);
        gl.shaderSource(this._vertShader, vertSrc);
        gl.compileShader(this._vertShader);

        this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.attachShader(this.program, this._fragShader);
        gl.shaderSource(this._fragShader, fragSrc);
        gl.compileShader(this._fragShader);

        gl.linkProgram(this.program);
    }

    use() {
        let gl = this._gl;

        if (this._firstUse) {
            this._firstUse = false;

            let attribCount = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES);
            for (let i = 0; i < attribCount; i++) {
                let attribInfo = gl.getActiveAttrib(this.program, i);
                this.attributes[attribInfo.name] = gl.getAttribLocation(this.program, attribInfo.name);
            }

            let uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
            for (let i = 0; i < uniformCount; i++) {
                let uniformInfo = gl.getActiveUniform(this.program, i);
                this.uniforms[uniformInfo.name] = gl.getUniformLocation(this.program, uniformInfo.name);
            }

            gl.deleteShader(this._vertShader);
            gl.deleteShader(this._fragShader);
        }

        gl.useProgram(this.program);
    }
}